package com.crawl.zhihu.parser;


import com.crawl.core.parser.ListPageParser;
import com.crawl.zhihu.ZhiHuHttpClient;
import com.crawl.zhihu.entity.Page;
import com.crawl.zhihu.entity.User;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.PathNotFoundException;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * 知乎用户详情列表页解析器
 */
public class ZhiHuUserListPageParser implements ListPageParser{
    private static ZhiHuUserListPageParser instance;
    public static ZhiHuUserListPageParser getInstance(){
        if (instance == null){
            synchronized (ZhiHuHttpClient.class){
                if (instance == null){
                    instance = new ZhiHuUserListPageParser();
                }
            }
        }
        return instance;
    }

    /**
     * 根据网页对象，解析出用户资料列表
     * @param page
     * @return 用户资料列表
     */
    @Override
    public List<User> parseListPage(Page page) {
        List<User> userList = new ArrayList<>();
        String baseJsonPath = "$.data.length()";
        DocumentContext dc = JsonPath.parse(page.getHtml());
        Integer userCount = dc.read(baseJsonPath);
        for (int i = 0; i < userCount; i++){
            User user = new User();
            String userBaseJsonPath = "$.data[" + i + "]";
            //userToken
            setUserInfoByJsonPth(user, "userToken", dc, userBaseJsonPath + ".url_token");
            //username
            setUserInfoByJsonPth(user, "username", dc, userBaseJsonPath + ".name");
            //hashId
            setUserInfoByJsonPth(user, "hashId", dc, userBaseJsonPath + ".id");
            //关注人数
            setUserInfoByJsonPth(user, "followees", dc, userBaseJsonPath + ".following_count");
            //位置
            setUserInfoByJsonPth(user, "location", dc, userBaseJsonPath + ".locations[0].name");
            //行业
            setUserInfoByJsonPth(user, "business", dc, userBaseJsonPath + ".business.name");
            //公司
            setUserInfoByJsonPth(user, "employment", dc, userBaseJsonPath + ".employments[0].company.name");
            //职位
            setUserInfoByJsonPth(user, "position", dc, userBaseJsonPath + ".employments[0].job.name");
            //学校
            setUserInfoByJsonPth(user, "education", dc, userBaseJsonPath + ".educations[0].school.name");
            //回答数
            setUserInfoByJsonPth(user, "answers", dc, userBaseJsonPath + ".answer_count");
            //提问数
            setUserInfoByJsonPth(user, "asks", dc, userBaseJsonPath + ".question_count");
            //文章数
            setUserInfoByJsonPth(user, "posts", dc, userBaseJsonPath + ".articles_count");
            //粉丝数
            setUserInfoByJsonPth(user, "followers", dc, userBaseJsonPath + ".follower_count");
            //赞同数
            setUserInfoByJsonPth(user, "agrees", dc, userBaseJsonPath + ".voteup_count");
            //感谢数
            setUserInfoByJsonPth(user, "thanks", dc, userBaseJsonPath + ".thanked_count");//感谢数
            try {
                //性别
                Integer gender = dc.read(userBaseJsonPath + ".gender");
                if (gender != null && gender == 1){
                    user.setSex("male");
                }
                else if(gender != null && gender == 0){
                    user.setSex("female");
                }
            } catch (PathNotFoundException e){
                //没有该属性
            }
            userList.add(user);
        }
        return userList;
    }
    /**
     * jsonPath获取值，并通过反射直接注入到user中
     * @param user user对象
     * @param fieldName user对象中的字段名
     * @param dc 文档上下文
     * @param jsonPath jsonPath表达式
     */
    private void setUserInfoByJsonPth(User user, String fieldName, DocumentContext dc , String jsonPath){
        try {
            //根据jsonPath表达式获取对应的值
            Object o = dc.read(jsonPath);
            //根据field字段名，获取对象的Field对象
            Field field = user.getClass().getDeclaredField(fieldName);
            //设置为可被访问
            field.setAccessible(true);
            //设置user对象的field字段的值
            field.set(user, o);
        } catch (PathNotFoundException e1) {
            //no results
        } catch (Exception e){
            e.printStackTrace();
        }
    }

}
